package QC.MessageBox.handler;

import QC.MessageBox.beans.WXPublic;
import QC.MessageBox.common.EmojiUtil;
import QC.MessageBox.common.PeriodicTime;
import QC.MessageBox.enums.ChannelType;
import QC.MessageBox.service.*;
import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Andaren on 2017/5/9.
 * Used for: 系统初始化服务
 */
public class BeforeStartInitHandler extends HandlerBase {
    private static final Logger LOGGER = LoggerFactory.getLogger(BeforeStartInitHandler.class);

    public BeforeStartInitHandler(HttpService httpService,
                                  WebClientService webClientService,
                                  MySQLService mySQLService,
                                  RedisService redisService,
                                  DataAccess dataAccess) {

        this.dataAccess = dataAccess;
        this.httpService = httpService;
        this.sqlService = mySQLService;
        this.redisService = redisService;
        this.webClientService = webClientService;
    }

    /**
     * 在系统第一次运行时
     *      1.初始化公众号信息，获取对应的access_token
     *      2.获取客服信息
     */

    /**
     * 系统第一次运行时准备
     */
    public BeforeStartInitHandler doInitWorkInFirstTime() {
        // 加载表情处理类
        EmojiUtil.startInit();
        // TODO test[这块儿代码完成后删除]
        // updateAccessTokenByAll();

        // 从数据库中获取所有公众号信息
        Future<List<WXPublic>> dbPublicFut = sqlService.getAllWxPublic();
        // 从app服务端获取公众号信息
        Future<List<WXPublic>> appPublicFut = webClientService.getPublicListFromAppBackground();
        CompositeFuture.all(dbPublicFut, appPublicFut)
                .setHandler(compositeAs -> {
                    if (compositeAs.failed()) {
                        LOGGER.info("获取所有公众号失败：" + compositeAs.cause());
                    } else {
                        // 从app传过来的公众号列表中提取本地数据库没有的公众号
                        List<WXPublic> dbPublicList = compositeAs.result().resultAt(0);
                        List<WXPublic> appPublicList = compositeAs.result().resultAt(1);
                        List<WXPublic> newPubliList = new ArrayList<>();
                        for (WXPublic appPublic : appPublicList) {
                            boolean isFind = false;
                            for(WXPublic dbPublic : dbPublicList) {
                                if(appPublic.getDeveloperId().equals(dbPublic.getDeveloperId())) {
                                    isFind = true;
                                }
                            }
                            if (!isFind) {
                                newPubliList.add(appPublic.setCreateTime(PeriodicTime.getCurrentTimeByyyyMMddHHmmss()));
                            }
                        }
                        if (newPubliList != null && newPubliList.size() > 0) {
                            for (WXPublic pub : newPubliList) {
                                // TODO 后面数据库用批量操作
                                sqlService.save(pub).setHandler(newPub -> {
                                    if (newPub.failed()) {
                                        LOGGER.info("新增公众号失败：" + newPub.cause().getMessage());
                                    } else {
                                        // *在启动时首次更新获取access_token
                                        updateAcessToken(newPub.result())
                                                .setHandler(updateAcessTokenAs -> {
                                                    if (updateAcessTokenAs.failed()) {
                                                        sqlService.delete(pub.getId(), WXPublic.class);
                                                    } else {
                                                        // 更新token成功：创建自定义菜单
                                                        /**
                                                         * TODO 正式环境下 屏蔽
                                                         *      测试环境下 打开
                                                         */
//                                                        webClientService.createCustomizeMenu(updateAcessTokenAs.result(), null);
                                                        // 历史粉丝处理
                                                        LOGGER.info("开始拉取历史粉丝");
                                                        if (ChannelType.WX.val() == pub.getChannelType()) {
                                                            // 微信公众号
                                                            generateHistoryFansByDeveloperId(pub.getDeveloperId());
                                                        } else if (ChannelType.WB.val() == pub.getChannelType()) {
                                                            // 微博公众平台
                                                            pullFansFromWB(pub);
                                                        }

                                                    }
                                                });
                                    }
                                });
                            }
                        }
                    }
                });

        // TODO 从app后台获取 微信用户-客服-客户 映射关系
        return this;
    }

    /**
     * 定时任务
     *      定时任务多时，将定时时间放在map中，遍历处理各个定时任务
     */
    public BeforeStartInitHandler doPeriodicTask(Vertx vertx) {
        vertx.setPeriodic(3600 * 1000, id -> {
            LOGGER.info("定时任务触发, current=[{}]", PeriodicTime.getCurrentTimeByyyyMMddHHmmss());
            updateAccessTokenByAll();
        });
        vertx.setPeriodic(60 * 1000, id -> {
            Future<Void> recordFut = Future.future();
            // 是否到00点00分
            if (PeriodicTime.isEndOfNight()) {
                LOGGER.info("定时上传聊天记录触发, current=[{}]", PeriodicTime.getCurrentTimeByyyyMMddHHmmss());
                String before = PeriodicTime.getCurrentDate();
                String beforeDateTime = PeriodicTime.getDateStrTheDayBeforeAMonth(before) + PeriodicTime.DAYTIME_MIN;
                // 搜索聊天历史记录
                sqlService.getMsgRecordsOrderByDate(null, beforeDateTime, null)
                        .compose(recordList ->
                                // 上传聊天历史记录
                                webClientService.sendHistoryMsgRecord(recordList)
                        )
                        .compose((Void) ->
                                        // 删除本地历史记录
                                        sqlService.deleteHistoryMsgRecored(beforeDateTime, null)
                                , recordFut);
            }
            recordFut.setHandler(as -> {
                if (as.failed()) {
                    LOGGER.info("[上传聊天历史记录]失败：" + as.cause().getMessage());
                } else {
                    LOGGER.info("[上传聊天历史记录]完成");
                }
            });
        });
        return this;
    }
}
